#include"memrw.h"
#include<dos.h>
#include<mem.h>
#include<stdio.h>
#include<alloc.h>
#include<process.h>

static MemBoxPtr   MBPtr=0;
// Usage: record memory block pointer to link structure
// 
void insertMemBox(BYTE * ptr)
{
       if(MBPtr == 0)  // alloc empty BOX at the end of link.
       {
                  MemBoxPtr NULLPtr=(MemBoxPtr)malloc(sizeof(struct MemBox));
		    if(NULLPtr == 0)
		    {
		             printf("alloc NULL MEMBOX area error \n");
                           exit(0);	   
		    }
		    NULLPtr ->ptr =0;
		    NULLPtr ->allocPtr =0;		    	

		    MBPtr = NULLPtr;
       }

	     
       MemBoxPtr TempPtr=(MemBoxPtr)malloc(sizeof(struct MemBox));
       if(TempPtr == 0)
       {
             printf("alloc  MEMBOX area error \n");
             exit(0);	   
       }	   
	TempPtr ->allocPtr= ptr;
	TempPtr ->ptr =MBPtr;

	MBPtr = TempPtr;

	return;
	   
}

//Usage: release memory block
//
void freeMemBox()
{
       MemBoxPtr TempPtr= MBPtr;
	BYTE * FreePtr;   

	while( TempPtr->allocPtr != 0)
	{
	       FreePtr = TempPtr ->allocPtr ;
		free(FreePtr);

              MBPtr= TempPtr ->ptr;
		free(TempPtr);

		TempPtr = MBPtr;            
		
	}
	return;
}

//calculate line address of a pointer
DWORD calcLineAddress(BYTE * Ptr)
{
            DWORD temp = FP_SEG(Ptr);
	     temp <<= 4;
	     temp += FP_OFF(Ptr);	 
	     return temp;	 
}



//Usage: align memory pointer
//IN:
//       ptr:  memory pointer to be aligned
//       alignNum:  memory boundary,  as 1KB , 16byte etc
//OUT:
//       memory pointer aligned
//
BYTE *alignMem(BYTE * ptr, int alignNum)
{
  	DWORD temp =FP_SEG(ptr);
	temp <<= 4;
	temp +=FP_OFF(ptr);        

	BYTE * alignPtr;
	if(temp & (alignNum - 1))
	{
		 temp=temp & (alignNum - 1);
		 WORD p= alignNum -(WORD)temp;
		 alignPtr = ptr +p;		 
	}
	else
	{
	          alignPtr = ptr;
	}
	return alignPtr;
}


/******************************************************************************
    Function:
        allocAlignMem

    Description:
	 allocate a aligned memory block, also insert the memory address in memory box.Clear memory block.
	 If you want a 1k memory size, and aligned 512 boundary, you must give size no less than
	 1k + 512 -1.
	 Invoker calcultate the memory size.

    Entry:
        int size
        int alignNum

    Exit:
        pointer which pointer to aligned address.
******************************************************************************/
BYTE *  allocAlignMemInBox(int size,   int alignNum)
{
          BYTE *StartPtr=(BYTE *)malloc(size);   //  alloc here
	   if(StartPtr ==0 ) 
	   {
	          printf("alloc memory descriptor area error \n");
                 exit(0);	  
	   }
   	   cleanBuffer(StartPtr,size);
	   insertMemBox(StartPtr); // record pointer .
	   return alignMem(StartPtr,  alignNum);
}



/******************************************************************************
    Function:
        allocAlignMem

    Description:
	 allocate a aligned memory block. Clear memory block.
	 If you want a 1k memory size, and aligned 512 boundary, you must give size no less than
	 1k + 512 -1.
	 Invoker calcultate the memory size.

    Entry:
        int size
        int alignNum

    Exit:
        pointer which pointer to aligned address.
******************************************************************************/
BYTE *  allocAlignMem(int size,   int alignNum)
{
          BYTE *StartPtr=(BYTE *)malloc(size);   //  alloc here
	   if(StartPtr ==0 ) 
	   {
	          printf("alloc memory descriptor area error \n");
                 exit(0);	  
	   }
//	   insertMemBox(StartPtr); // record pointer .
	   cleanBuffer(StartPtr,size);
	   return alignMem(StartPtr,  alignNum);
}


//clean memory  
void cleanBuffer(BYTE * bufferPtr , int size)
{
        for (int i=0; i<size ;i++)  bufferPtr[i] =0;
        return;
}

void  memCopy(void * dest, const void * src ,  int n)
{
           memcpy(dest, src,n);
           return ;		   
}

void  dump(BYTE * StartPtr, int n)
{

//           printf("\n");	 
           for(int i=0;i<n;i++)
           {
                    printf("%02x",StartPtr[i]);
		      printf(" ");
		      if(i && (i+1)%8 == 0 &&  (i+1)%16) printf(" -- ");
		      if(i && (i+1)%16 ==0)printf("\n");	  
		  			  
           }
  
	   return;	   
}

void  dumpDWORD(DWORD * StartPtr, int n)
{

//           printf("\n");	 
           for(int i=0;i<n;i++)
           {
                    printf("%08lx",StartPtr[i]);
		      printf(" ");
//		      if(i && (i+1)%8 == 0 &&  (i+1)%16) printf(" -- ");
		      if(i && (i+1)%4 ==0)printf("\n");	  
		  			  
           }
  
	   return;	   
}



